#include "savedatathread.h"
#include "parsedatathread.h"

extern int CollectType;  // 1:连续采集;2:触发采集
extern int Frequency;
extern int TimeLength;
extern int VoltageLevel;
extern bool IsCollect;
extern QString CurrentPath;
extern QVector<QString> DataDates;
extern QMutex MuteDisp;
extern QMutex MuteSave;

SaveDataThread::SaveDataThread(QObject *parent) : QObject(parent)
{
}

QString SaveDataThread::PackFileName(DateTimeInfo DtInfo, int Ch)
{
    QString FileName = CurrentPath + "/" + DtInfo.Year + "/" + DtInfo.YearMonth + "/" +
             DtInfo.Date + "/" + DtInfo.DateTime;
    FileName = QString("%1/ANKE_%2_%3.smp").
            arg(FileName).
            arg(Ch, 2, 10, QLatin1Char('0')).
            arg(DtInfo.DateTime);

    return FileName;
}

bool SaveDataThread::CreateFilePath(DateTimeInfo time)
{
    QString FileName = CurrentPath + "/" + time.Year + "/" + time.YearMonth + "/" +
             time.Date + "/" + time.DateTime;
    QDir dir(FileName);
    if(dir.exists()) {
        return true;
    }
    else {
        if(dir.mkpath(FileName))
            return true;
        else
            return false;
    }
}

void SaveDataThread::SaveIndexFile(DateTimeInfo time)
{
    QString FilePath = CurrentPath + "/" + time.Year + "/" + time.YearMonth + "/" +
             time.Date + "/" + time.DateTime;
    QString FileName = QString("%1/ANKE_%2.indx").
            arg(FilePath).
            arg(time.DateTime);
    IndexFile indx;
    indx.SetFileName(FileName);
    indx.SetString("EVENT", "FILEPATH", CurrentPath);    // 文件路径
    indx.SetString("EVENT", "PROJECTPATH", CurrentPath); // 工程路径
    indx.SetString("EVENT", "PROJECTNAME", "ANKE");      // 工程名称
    indx.SetInt("EVENT", "SAMPPOINTNUM", Frequency * TimeLength);
    indx.SetInt("EVENT", "TIME_LONGTH(s)", TimeLength);
    indx.SetInt("EVENT", "TRIGLAGPOINTNUM", 0);
    indx.SetInt("EVENT", "CH_NUM", CHANNELCOUNT);
    indx.SetInt("EVENT", "ETrigCH_NUM", 0);
    indx.SetInt("EVENT", "dpoint", 5);
    indx.SetInt("EVENT", "LongWndMoveCoe", 0);
    indx.SetInt("EVENT", "ShortWndMoveStep", 1);
    indx.SetInt("EVENT", "QuakeEvent", 1);
    indx.SetInt("EVENT", "EarthSoundEvent", 0);
    indx.SetString("EVENT", "START_TIME", time.DateTime);
    int Cnt = 0;
    for(int i = 0; i < CHANNELCOUNT; i++) {
        ++Cnt;
        indx.SetString(QString("CHANNEL_%1").arg(i + 1), "ChannelN0.",
                       QString("%1").arg(i + 1));
        indx.SetString(QString("CHANNEL_%1").arg(i + 1), "TestNo.",
                       QString("%1").arg(i + 1, 2, 10, QLatin1Char('0')));
        indx.SetString(QString("CHANNEL_%1").arg(i + 1),
                       "SampFreq(Hz).", QString::number(Frequency));
        indx.SetString(QString("CHANNEL_%1").arg(i + 1),
                       "Gain", "1");
        indx.SetString(QString("CHANNEL_%1").arg(i + 1),
                       "Sensitivity(mv/EU)", "1");
        indx.SetString(QString("CHANNEL_%1").arg(i + 1),
                       "ProjectUnit", "mV");
        indx.SetString(QString("CHANNEL_%1").arg(i + 1),
                       "Remarks", "Remarks");
        indx.SetString(QString("CHANNEL_%1").arg(i + 1),
                       "CH_AllTime", "500");
        indx.SetString(QString("CHANNEL_%1").arg(i + 1),
                       "CH_WinTime", "100");
        indx.SetString(QString("CHANNEL_%1").arg(i + 1),
                       "CH_AllTrigVolt", "10");
        indx.SetString(QString("CHANNEL_%1").arg(i + 1),
                       "CH_WinTrigVolt", "6");
        indx.SetString(QString("CHANNEL_%1").arg(i + 1),
                       "CH_ConductionLog", "与");
        indx.SetString(QString("CHANNEL_%1").arg(i + 1),
                       "CH_AELimitValue", "0");
        indx.SetString(QString("CHANNEL_%1").arg(i + 1),
                       "CH_AEPreAlarm", "1000");
        indx.SetString(QString("CHANNEL_%1").arg(i + 1),
                       "CH_AEAlarm", "2000");
        indx.SetString(QString("CHANNEL_%1").arg(i + 1),
                       "CH_AEFreqPreAlarm", "10");
        indx.SetString(QString("CHANNEL_%1").arg(i + 1),
                       "CH_AEFreqAlarm", "20");
        indx.SetString(QString("CHANNEL_%1").arg(i + 1),
                       "strSensorType", "微震");
    }
    qDebug() << "Index Cnt = " << Cnt;
    indx.WriteIndexFile();
    JLog log;
    log.WriteLog("[DATA] save data successful.");
}

void SaveDataThread::ReceviceData(DateTimeInfo time, QVector<float>* SrcData)
{
    JLog log;
    log.WriteLog("[SAVE] Saving data...");
    QVector<float> data[CHANNELCOUNT];
    if(SrcData[0].size() > 0) {
        QMutexLocker loker(&MuteSave);
        for(int i = 0; i < CHANNELCOUNT; i++) {
            data[i] = SrcData[i];
        }
    }
    qDebug() << "Save time: " << time.DateTime;
    QString FileName;
    int Length = data[0].size();
//    if((IsCollect) && (CollectType == 2))
//        emit TrigDataTip();

    // 检查存储数据时间节点成配置文件
    WriteConfig(time);

    // 检查SD卡存储空间，存储空间不够时清除历史第一天数据
    IsSDRoomSmall();

    for(int i = 0; i < CHANNELCOUNT; i++) {
        // 1. 组装文件目录和文件名
        if(CreateFilePath(time))
            FileName = PackFileName(time, i + 1);
        else
            return;

        // 2. 初始化数据文件头信息, 保存数据文件
        df.InitHeaderInfo(100, 24, Length, Frequency, CHANNELCOUNT, i + 1,
                          QString("%1").arg(i + 1, 2, 10, QLatin1Char('0')),
                          1, 1, "mV", "remark");
        if(!df.WriteChData(FileName, data[i].data(), Length)) {
            // 保存数据失败提示
            emit SaveDataError();
        }
    }

    // 3. 保存indx文件
    SaveIndexFile(time);
    if(CollectType == 2)
        emit FinishedTrigSave();
}

void SaveDataThread::WriteConfig(DateTimeInfo time)
{
    if(DataDates.empty()) {
        DataDates.push_back(time.Date);
        QSettings cf("/home/default/Collector/Config.cfg", QSettings::IniFormat);
        cf.setValue("/Config/Count", 1);
        cf.setValue("/Config/0", time.Date);
    }
    else {
        bool IsSave = true;
        for(int i = DataDates.size() - 1; i >= 0 ; i--) {
            if(time.Date == DataDates.at(i)) {
                IsSave = false;
                break;
            }
        }
        if(IsSave) {
            DataDates.push_back(time.Date);
            QSettings cf("Config.cfg", QSettings::IniFormat);
            cf.setValue("/Config/Count", DataDates.size());
            QString head = QString("/Config/%1").arg(QString::number(DataDates.size() - 1));
            cf.setValue(head, time.Date);
        }
    }
}

bool SaveDataThread::IsSDRoomSmall()
{
    QProcess pro;
    pro.start("df -h");
    pro.waitForFinished();
    QString info = pro.readAllStandardOutput();
    QStringList str = info.split("\n");
    if(str.size() <= 0)
        return false;
    for(int i = 0; i < str.size(); i++) {
        QString tmp = str.at(i);
        if(tmp.contains("/dev/mmcblk0p1")) {
            QStringList len = str.at(i).split(" ", QString::SkipEmptyParts);
            QString SDSize = len.at(3);
            if(SDSize.contains("M")) {
                SDSize = SDSize.left(SDSize.length() - 1);
                if(SDSize.toFloat() < 100) {
                    DeleteSDDataFile();
                }
            }
            break;
        }
    }
}

void SaveDataThread::DeleteSDDataFile()
{
    for(int i = 0; i < DataDates.size(); i++) {
        QString year = DataDates.at(i).mid(0, 4);
        QString yearM = DataDates.at(i).mid(5, 2);
        QString cmd = QString("/mnt/%1/%1-%2/%3/").
                arg(year).
                arg(yearM).
                arg(DataDates.at(i));
        // 1. judge the dir is exist
        QDir dir(cmd);
        QSettings cf("/home/default/Collector/Config.cfg", QSettings::IniFormat);
        if(dir.exists()) {
            // 2. delete the file data
            QProcess::execute("rm -rf " + cmd);
            JLog log;
            log.WriteLog("delete data file: " + DataDates.at(i));

            // 3. remote the first date recorde
            DataDates.remove(i);

            // 4. delete config file date
            QString head = QString("/Config/%1").arg(QString::number(DataDates.size()));
            cf.remove(head);

            // 5. resort the config file
            cf.setValue("/Config/Count", DataDates.size());
            for(int j = 0; j < DataDates.size(); j++) {
                head = QString("/Config/%1").arg(QString::number(j));
                cf.setValue(head, DataDates.at(j));
            }

            break;
        }
        else {
            // 2. remote the first date recorde
            DataDates.remove(i);

            // 3. delete config file date
            QString head = QString("/Config/%1").arg(QString::number(DataDates.size()));
            cf.remove(head);

            // 4. resort the config file
            cf.setValue("/Config/Count", DataDates.size());
            for(int j = 0; j < DataDates.size(); j++) {
                head = QString("/Config/%1").arg(QString::number(j));
                cf.setValue(head, DataDates.at(j));
            }
        }
    }
}
